package cn.stylefeng.guns.modular.business.service.impl;

import cn.stylefeng.guns.base.consts.ConstantsContext;
import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo;
import cn.stylefeng.guns.config.redis.RedisHandler;
import cn.stylefeng.guns.config.redis.redis.Redis0Template;
import cn.stylefeng.guns.config.redis.redis.util.Redishandler0;
import cn.stylefeng.guns.config.redis.redis.util.Redishandler2;
import cn.stylefeng.guns.config.redis.redis.util.Redishandler3;
import cn.stylefeng.guns.core.*;
import cn.stylefeng.guns.core.schedue.spring.UserGradeTask;
import cn.stylefeng.guns.modular.business.common.Constants;
import cn.stylefeng.guns.modular.business.entity.*;
import cn.stylefeng.guns.modular.business.mapper.BatchOrderMapper;
import cn.stylefeng.guns.modular.business.mapper.OrderMapper;
import cn.stylefeng.guns.modular.business.model.RedisINCRDTO;
import cn.stylefeng.guns.modular.business.model.params.*;
import cn.stylefeng.guns.modular.business.model.result.OrderResult;
import cn.stylefeng.guns.modular.business.service.*;
import cn.stylefeng.guns.sys.core.constant.CertificationStatus;
import cn.stylefeng.guns.sys.core.shiro.ShiroKit;
import cn.stylefeng.guns.sys.core.util.DateUtil;
import cn.stylefeng.guns.sys.core.util.HttpUtil;
import cn.stylefeng.guns.sys.core.util.ODDGenerator;
import cn.stylefeng.guns.sys.core.util.StringUtils;
import cn.stylefeng.guns.sys.modular.system.entity.User;
import cn.stylefeng.guns.sys.modular.system.service.UserService;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.exception.ServiceException;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author jwj
 * @since 2019-07-12
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private CardQuotaService cardQuotaService;

    @Autowired
    private UserService userService;

    @Autowired
    private CardService cardService;

    @Autowired
    private MoneyLogService moneyLogService;

    @Autowired
    private UserPropertyService userPropertyService;

    @Autowired
    private Redishandler0 redishandler0;

    @Autowired
    private Redishandler3 redishandler3;

    @Autowired
    private Redishandler2 redishandler2;

    @Autowired
    private Redis0Template redis0Template;

    @Autowired
    private MessageNoticeService messageNoticeService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private UserGradeTask userGradeTask;

    @Autowired
    RedisHandler redisHandler;

    @Autowired
    private PinChannelService pinChannelService;

    @Autowired
    private BatchOrderMapper batchOrderMapper;

    /**
     * rabbitmq地址
     */
    @Value("${file.rabbitmqUrl}")
    private String rabbitUrl;

    @Override
    public void add(OrderParam param){
        Order entity = getEntity(param);
        this.save(entity);
    }

    @Override
    public void delete(OrderParam param){
        this.removeById(getKey(param));
    }

    @Override
    public void update(OrderParam param){
        Order oldEntity = getOldEntity(param);
        Order newEntity = getEntity(param);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
    }

    @Override
    public OrderResult findBySpec(OrderParam param){
        return null;
    }

    /**
     * 查询单条数据
     *
     * @param orderId
     * @author jwj
     * @Date 2019-07-12
     */
    @Override
    public OrderResult findById(String orderId) {
        Order order = this.getById(orderId);
        OrderResult result = new OrderResult();
        if (order != null ) {
            OrderItem orderItem = orderItemService.getOne(new QueryWrapper<OrderItem>().eq("delete_flag", RecoverConst.DEL_FLAG_FALSE).eq("order_id", order.getOrderId()));
            ToolUtil.copyProperties(order, result);
            result.setItemAmount(orderItem.getAmount());
            result.setCardNo(orderItem.getCardNo());
            result.setCardPassword(orderItem.getCardPassword());
            result.setCardCataoryId(orderItem.getCardCataoryId());
            result.setCardCataoryName(orderItem.getCardCataoryName());
            result.setCardQuotaId(orderItem.getCardQuotaId());
            result.setCardQuotaName(orderItem.getCardQuotaName());
            result.setCreateTimeStr(DateUtil.convert(result.getCreateTime()));
            result.setSubQuota(orderItem.getSubQuota());
            result.setItemQuota(orderItem.getItemQuota());
            result.setCardTypeName(orderItem.getCardTypeName());
            if (result.getUpdateTime() != null) {
                result.setUpdateTimeStr(DateUtil.convert(result.getUpdateTime()));
            }
        }
        return result;
    }

    @Override
    public List<OrderResult> findListBySpec(OrderParam param){
        return null;
    }

    @Override
    public LayuiPageInfo findPageBySpec(OrderParam param){
        Page pageContext = getPageContext();
        //如果是3，那么则指定为需要管理员手动处理
        if (param.getOrderStatus() != null && param.getOrderStatus().equals(3)) {
            param.setOrderStatus(null);
            param.setOrderDoingStatus(RecoverConst.ORDER_DOING_STATUS_ADMIN);
        }
        IPage page = this.baseMapper.customPageList(pageContext, param);
        return LayuiPageFactory.createPageInfo(page);
    }

    private UserGrade getGrade(int level) {
        String gradeStr = redishandler0.getHash(RecoverConst.USER_GRADE_REDIS_KEY, "", level + "");
        UserGrade grade = JSONObject.parseObject(gradeStr, UserGrade.class);
        return grade;
    }

    /**
     * 创建订单
     *
     * @param param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseData create(OrderParam param) {

        /**
         * TODO 为了前端处理，此处显示
         * 1、先判断
         * 2、保存
         */
        //1\根据用户的等级，获取面值的比率判断比率和提交的比率是否一致
        User user = userService.getById(param.getOwnerUserId());
        if (user == null) {
            //throw new ServiceException(500, "用户错误");
            return ResponseData.error(500, "用户错误");
        }
        if(!user.getCertificationStatus().equals(CertificationStatus.PASS.getCode())) {
            //throw new ServiceException(800, "用户未实名");
            return ResponseData.error(800, "用户未实名");
        }
        String quotaStr = redishandler2.getHash(RecoverConst.QUOTA_HASH_KEY, "", param.getCardQuotaId().toString());
        if (StringUtils.isEmpty(quotaStr)) {
            //throw new ServiceException(500, "不存在此类卡面值");
            return ResponseData.error(500, "不存在此类卡面值");
        }
        UserProperty userProperty = userPropertyService.getById(param.getOwnerUserId());
        UserGrade userGrade = getGrade(userProperty.getGradeLevel());
        if (userProperty == null) {
            //throw new ServiceException(500, "用户等级错误");
            return ResponseData.error(500, "用户等级错误");
        }
        //验证用户等级折扣总价和提交总价是否一样
        CardQuota quota = JSONObject.parseObject(quotaStr, CardQuota.class);
        if (quota.getRecoverRate() == null) {
            //throw new ServiceException(500, "卡类折扣未设置");
            return ResponseData.error(500, "卡类折扣未设置");
        }

        if(!quota.getAmount().equals(param.getSubQuota())) {
            //throw new ServiceException(500, "面值错误");
            return ResponseData.error(500, "面值错误");
        }
        //是否已经提交过卡号
        OrderParam countParam = new OrderParam();
        if (StringUtils.isNotEmpty(param.getCardNo())) {
            countParam.setCardNo(param.getCardNo());
        }
        countParam.setCardPassword(param.getCardPassword());
        Long isSubCard = this.baseMapper.countByCondition(countParam);

        if (isSubCard > 0) {
            //throw new ServiceException(500, "已经存在相同的卡密");
            return ResponseData.error(500, "已经存在相同的卡密");
        }
        //如果是vip等级，那么折扣取回收最高折扣，如果不是，那么取递减后的折扣
        Float userRecoverRate = 0F;
        if (userProperty.getGradeLevel().equals(UserGradeLevel.second_level.getCode()) || userProperty.getRecommendLevel().equals(0)) {
            userRecoverRate = quota.getRecoverRate();
        } else {
            userRecoverRate = quota.getRecoverRate() - ((userProperty.getRecommendLevel() - 1) * userGrade.getDecrRate().floatValue());
        }

        BigDecimal amount = new BigDecimal("" + userRecoverRate).multiply(new BigDecimal("" + quota.getAmount())).setScale(2, BigDecimal.ROUND_HALF_UP);
        Float payRate = userRecoverRate;
        if (amount.compareTo(param.getAmount()) != 0) {
            //throw new ServiceException(500, "提交折扣和后台折扣不一致");
            return ResponseData.error(500, "提交折扣和后台折扣不一致");
        }

        //this.userService.assertAuth(param.getOwnerUserId());
        Order order = new Order();
        OrderItem item = new OrderItem();
        ToolUtil.copyProperties(param, order);
        order.setOwnerUser(order.getOwnerUser() != null ? order.getOwnerUser() : user.getAccount());
        //生成订单号
        order.setOrderNo(ODDGenerator.getC(StringUtils.replace(UUID.randomUUID().toString(), "-", "")));
        item.setAmount(param.getAmount());
        //平台成本
        BigDecimal costAmount = new BigDecimal("" + quota.getAmount() * quota.getCostRate()).setScale(2, BigDecimal.ROUND_HALF_UP);
        order.setCostRate(quota.getCostRate());
        order.setCostAmount(costAmount);
        order.setPayAmount(amount);
        order.setPayRate(payRate);
        order.setOrderRate(payRate);
        order.setQuota(quota.getAmount());
        if (param.getBatchOrderId() != null) {
            order.setBatchOrderId(param.getBatchOrderId());
        }

        //预计平台收益  成本减去提交的金额
        order.setExpectProfit(costAmount.subtract(amount));
        item.setCardCataoryId(param.getCardCataoryId());
        item.setCardCataoryName(param.getCardCataoryName());
        //获取上一级的分类
        String cateStr = redishandler3.getHash(Constants.CATEGORY_SELF_HASH_KEY, "", param.getCardCataoryId().toString());
        if (StringUtils.isNotEmpty(cateStr)) {
            Category category = JSONObject.parseObject(cateStr, Category.class);
            if (category.getPid() != null) {
                String parentStr = redishandler3.getHash(Constants.CATEGORY_SELF_HASH_KEY, "", category.getPid().toString());
                if (StringUtils.isNotEmpty(parentStr)) {
                    Category parentCate = JSONObject.parseObject(parentStr, Category.class);
                    item.setCardTypeId(parentCate.getCategoryId());
                    item.setCardTypeName(parentCate.getName());
                }
            }
        }
        item.setCardNo(param.getCardNo());
        item.setCardPassword(param.getCardPassword());
        item.setCardQuotaId(param.getCardQuotaId());
        item.setCardQuotaName(param.getCardQuotaName());
        item.setSubQuota(param.getSubQuota());
        item.setItemQuota(quota.getAmount());
        this.save(order);
        item.setOrderId(order.getOrderId());
        orderItemService.save(item);
        //如果是自动类，提交自动处理队列
        String categoryStr = redisHandler.getGlobalRedisTemplate().getHash(Constants.CATEGORY_SELF_HASH_KEY, "", param.getCardCataoryId().toString());
        Category category = JSONObject.parseObject(categoryStr, Category.class);
        List<PinChannel> pinChannelList = pinChannelService.list(new QueryWrapper<PinChannel>().eq("status", 1).eq("delete_flag", RecoverConst.DEL_FLAG_FALSE).eq("category_id", param.getCardCataoryId()));
        if(pinChannelList != null && pinChannelList.size() > 0) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("order", order);
            jsonObject.put("orderItem", item);
            int index = (int) (Math.random() * pinChannelList.size());
            jsonObject.put("channel", pinChannelList.get(index));
            try {
               String result = HttpUtil.sendPostJson(rabbitUrl, jsonObject.toJSONString(), "utf-8");
                if (!"ok".equals(result)) {
                    throw new ServiceException(500, "自动通道未设置，请通知管理员设置");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ResponseData.success();
    }

    /**
     * 审核订单
     *
     * @param param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean approve(OrderParam param, boolean approve) {
        /**
         * 1、获取订单和订单明细
         * 2、修改订单状态和审核人
         * 3、通过保存至卡号表，同时添加用户余额记录
         */
        Order order = null;
        if (param.getOrderId() != null) {
            order = this.getById(param.getOrderId());
        } else {
            order = this.getOne(new QueryWrapper<Order>().eq("order_no", param.getOrderNo()));
        }
        if(order != null && order.getOrderStatus() != OrderStatusState.SUBMIT.getCode()) {
            log.info("订单：" +order.getOrderNo() + "申请处理, 但是已经处理，无需再处理");
            return true;
        }
        if (order != null ) {
            OrderItem orderItem = orderItemService.getOne(new QueryWrapper<OrderItem>().eq("delete_flag", RecoverConst.DEL_FLAG_FALSE).eq("order_id", order.getOrderId()));
            if (orderItem != null) {
                //TODO 如果销卡价格和设置价格不一致，需要管理员手动审核
                CardQuota quota = cardQuotaService.getById(orderItem.getCardQuotaId());
                if (param.getCostAmount() != null) {
                    order.setCostAmount(param.getCostAmount());
                    if (!param.isAdminApprove() && approve && param.getCostAmount().compareTo(order.getCostAmount()) < 0) {
                        order.setOrderDoingStatus(RecoverConst.ORDER_DOING_STATUS_ADMIN);
                        order.setPayAmount(param.getCostAmount());
                        this.updateById(order);
                        return true;
                    }
                }
                if (param.getItemQuota() != null) {
                    orderItem.setItemQuota(param.getItemQuota());
                }
                Long userId = null;
                if (!param.isAdminApprove()) {
                    String gunsAdminUserId = (String) ConstantsContext.getConstntsMap().get("GUNS_ADMIN_USER_ID");
                    userId = Long.valueOf(gunsAdminUserId);
                } else {
                    userId = ShiroKit.getUserNotNull().getId();
                }
                User user = userService.getById(userId);
                order.setApproveUser(user.getName());
                order.setApproveUserId(user.getUserId());

                if (param.getPayAmount() != null) {
                    order.setPayAmount(param.getPayAmount());
                } else if (param.getPayRate() != null){
                    order.setPayAmount(new BigDecimal((orderItem.getItemQuota() * param.getPayRate()) + "").setScale(2, BigDecimal.ROUND_HALF_UP));
                } else {
                    order.setPayAmount(new BigDecimal((orderItem.getItemQuota() * order.getOrderRate()) + "").setScale(2, BigDecimal.ROUND_HALF_UP));
                }
                if (param.getPayRate() != null) {
                    order.setPayRate(param.getPayRate());
                }

                if (approve) {
                    order.setRealProfit(order.getCostAmount().subtract(order.getPayAmount()));
                    if (order.getRealProfit().compareTo(BigDecimal.ZERO) < 0) {
                        log.info("平台利润负数，不予通过");
                        order.setOrderDoingStatus(RecoverConst.ORDER_DOING_STATUS_ADMIN);
                        this.updateById(order);
                        return true;
                    }
                    if (param.isAdminApprove()) {
                        order.setRemark(StringUtils.isNotEmpty(param.getRemark()) ? param.getRemark() : "销卡成功");
                    } else {
                        order.setRemark("销卡成功");
                        order.setThirdRemark(param.getRemark());
                    }
                    order.setOrderStatus(OrderStatusState.PASS.getCode());
                } else {
                    if (param.isAdminApprove()) {
                        order.setRemark(StringUtils.isNotEmpty(param.getRemark()) ? param.getRemark() : "销卡失败");
                    } else {
                        order.setRemark("销卡失败");
                        order.setThirdRemark(param.getRemark());
                    }
                    order.setOrderStatus(OrderStatusState.UN_PASS.getCode());
                }
                //添加第三方订单号 (收卡啦)
                order.setThirdOrderNo(param.getThirdOrderNo());
                updateById(order);
                orderItemService.updateById(orderItem);
                if (!approve) {
                    messageNoticeService.add("销卡失败通知", "您提交的" + orderItem.getSubQuota() +"元"+orderItem.getCardCataoryName() + "核销失败，失败原因为：" + param.getRemark(), MessageNoticeType.system.getCode(), order.getOwnerUserId());
                }
                //获取订单拥有者
                User ownerUser = userService.getById(order.getOwnerUserId());
                //审核成功
                if (approve) {
                    //保存卡
                    Card card = cardService.getOne(new QueryWrapper<Card>().eq("delete_flag", RecoverConst.DEL_FLAG_FALSE).eq("order_id", order.getOrderId()));
                    if (card != null) {
                        throw new RuntimeException("该订单已经审核通过");
                    }
                    card = new Card();
                    card.setAmount(order.getPayAmount());
                    card.setCardCataoryId(orderItem.getCardCataoryId());
                    card.setCardCataoryName(orderItem.getCardCataoryName());
                    card.setCardNo(orderItem.getCardNo());
                    card.setCardPassword(orderItem.getCardPassword());
                    card.setCostAmount(order.getCostAmount());
                    card.setCostRate(quota.getCostRate());
                    card.setRecoverRate(param.getPayRate());
                    card.setCreateUser(order.getOwnerUser());
                    card.setCreateUserId(order.getOwnerUserId());
                    card.setOrderId(order.getOrderId());
                    card.setQuota(param.getItemQuota());
                    card.setQuotaId(quota.getCardQuotaId());
                    card.setQuotaName(quota.getName());
                    card.setCardCataoryName(orderItem.getCardCataoryName());
                    card.setCardCataoryId(orderItem.getCardCataoryId());
                    card.setOrderNo(order.getOrderNo());
                    cardService.save(card);
                    //添加用户余额
                    userService.update(new UpdateWrapper<User>().setSql("amount=amount+" + order.getPayAmount()).eq("user_id", order.getOwnerUserId()));
                    //保存用户余额记录，更新用户余额
                    saveMoneyLog(order.getOrderId(), card, order.getPayAmount(), order.getOrderNo());
                    //分润
                    //BigDecimal sysAmount = card.getCostAmount().subtract(card.getAmount());
                    List<RedisINCRDTO> list = saveProfile(quota, order.getOwnerUserId());
                    messageNoticeService.add("销卡成功通知", "您提交的" + card.getQuota() + "元" + orderItem.getCardCataoryName() + "已经成功核销，实际面值为" + orderItem.getItemQuota() + ", 到账金额为：" + order.getPayAmount(), MessageNoticeType.system.getCode(), order.getOwnerUserId());
                    if (ownerUser!=null&&ownerUser.getMessagePush().equals("0")) {
                        //发送微信模板消息
                        log.info("开始发送微信消息");
                        sendSuccessMessageToUser(ownerUser.getOpenid(), card.getQuota(), orderItem.getCardTypeName(), orderItem.getCardCataoryName(), order.getPayAmount());
                    }
                    if (list != null) {
                        //更新缓存放在最后，回滚的话，可以不用操作缓存
                        List<Object> redisResult = redis0Template.executePipelined(new RedisCallback<Object>() {
                            @Override
                            public String doInRedis(RedisConnection connection) throws DataAccessException {
                                for (RedisINCRDTO redisINCRDTO : list) {
                                    connection.incrBy((redisINCRDTO.getRedisPreKey() + redisINCRDTO.getRedisKey()).getBytes(), redisINCRDTO.getValue());
                                }
                                return null;
                            }
                        });
                    }
                    //判断面值是否足够升级
                    //userGradeTask.configureTasks(order.getOwnerUserId());
                    if (order.getBatchOrderId() != null) {
                        //修改批次数量
                        batchOrderMapper.decrDoingNum(1, null, order.getBatchOrderId());
                    }

                    return true;
                } else {
                    if (ownerUser != null && "0".equals(ownerUser.getMessagePush())) {
                        //发送微信模板消息
                        sendFailMessageToUser(ownerUser.getOpenid(), order.getQuota(), orderItem.getCardTypeName(), orderItem.getCardCataoryName(), order.getAmount(), order.getRemark());
                    }

                    if (order.getBatchOrderId() != null) {
                        //修改批次数量
                        batchOrderMapper.decrDoingNum(null, 1, order.getBatchOrderId());
                    }
                }
            }
        }
        return false;
    }

    private void sendSuccessMessageToUser(String openId, Integer quota, String cardTypeName, String cardCataoryName, BigDecimal payAmount) {
        MessageDTO messageDTO = new MessageDTO();
        messageDTO.setUserIdList(Collections.singletonList(openId));
        messageDTO.setMessageType(MessageType.RECLAIM_SUCCESS);
        WxMessageDTO wxMessageDTO = new WxMessageDTO();
        wxMessageDTO.setFirst("您提交的" + quota + "元" + cardCataoryName + "已核销成功");
        wxMessageDTO.setKeyword1(cardTypeName);
        wxMessageDTO.setKeyword2(cardCataoryName);
        wxMessageDTO.setKeyword3(payAmount.toString());
        wxMessageDTO.setKeyword4(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        wxMessageDTO.setRemark("感谢您的支持");
        messageDTO.setData(wxMessageDTO);
        messageService.sendTemplateMessage(messageDTO);
    }

    private void sendFailMessageToUser(String openId, Integer amount, String cardTypeName, String cardCataoryName, BigDecimal payAmount, String remark) {
        MessageDTO messageDTO = new MessageDTO();
        messageDTO.setUserIdList(Collections.singletonList(openId));
        messageDTO.setMessageType(MessageType.RECLAIM_FAIL);
        WxMessageDTO wxMessageDTO = new WxMessageDTO();
        wxMessageDTO.setFirst("您提交的" + amount + "元" + cardCataoryName + "核销失败");
        wxMessageDTO.setKeyword1(cardTypeName);
        wxMessageDTO.setKeyword2(cardCataoryName);
        wxMessageDTO.setKeyword3(remark);
        wxMessageDTO.setKeyword4(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        wxMessageDTO.setRemark("感谢您的支持");
        messageDTO.setData(wxMessageDTO);
        messageService.sendTemplateMessage(messageDTO);
    }

    @Override
    public Page<OrderResult> getMyOrders(Page page, OrderQueryParam orderQueryParam) {

        return baseMapper.getMyOrders(page, orderQueryParam);
    }

    /**
     * 1、计算上级利润
     * 2、获取上级余额，
     * 3、添加上级分润记录
     * 4、更新上级余额
     * @param userProperty
     * @param mapParent
     * @param gradeList
     */
    private void addProfile(UserProperty userProperty, Map<Long, UserProperty> mapParent, Map<Object, Object> gradeList, Integer parentLevel, CardQuota quota, List<RedisINCRDTO> list, Long comeUserId) {
        if (mapParent.get(userProperty.getParentId()) != null) {
            UserProperty parent = mapParent.get(userProperty.getParentId());
            String gradeStr = String.valueOf(gradeList.get(parent.getGradeLevel().toString()));
            if (StringUtils.isNotEmpty(gradeStr)) {
                UserGrade grade = JSONObject.parseObject(gradeStr, UserGrade.class);
                Long oldAmount = 0L;
                try {
                    BigDecimal payRate = grade.getDecrRate();
                    //如果是内置用户，不参与
                    if (parent.getParentId() == null || parent.getRecommendLevel() == 0) {
                        payRate = null;
                    }
                    if (payRate != null && payRate.compareTo(BigDecimal.ZERO) > 0) {
                        payRate = payRate.setScale(4,BigDecimal.ROUND_HALF_UP);
                        oldAmount = redishandler0.incr(RecoverConst.MONEY_USER_AMOUNT, parent.getUserId().toString(), 0);
                        BigDecimal oldAmountBig = new BigDecimal(oldAmount).divide(new BigDecimal(1000));
                        BigDecimal profile = new BigDecimal("" + quota.getAmount()).multiply(payRate);
                        BigDecimal newAmount = oldAmountBig.add(profile);
                        MoneyLog moneyLog = new MoneyLog();
                        moneyLog.setAmount(profile);
                        moneyLog.setNewAmount(newAmount);
                        moneyLog.setOldAmount(oldAmountBig);
                        if (parentLevel > 1) {
                            moneyLog.setRemark("您的间推用户realName销卡成功，给您贡献：" + profile.toString());
                            moneyLog.setType(MoneyLogType.CARD_EXTEND_J.getCode());
                        } else {
                            moneyLog.setRemark("您的直推用户realName销卡成功，给您贡献：" + profile.toString());
                            moneyLog.setType(MoneyLogType.CARD_EXTEND_Z.getCode());
                        }
                        //销卡
                        moneyLog.setSecondType(1);
                        moneyLog.setUserId(parent.getUserId());
                        moneyLog.setComeUserId(comeUserId);

                        //moneyLog.setUserName(parent.get);
                        userService.update(new UpdateWrapper<User>().setSql("amount=amount+" + profile).eq("user_id", parent.getUserId()));
                        moneyLogService.save(moneyLog);
                        messageNoticeService.add("推广分润提醒", "您的直推用户销卡成功，给您贡献了：" + profile.toString(), MessageNoticeType.system.getCode(), parent.getUserId());
                        RedisINCRDTO redisINCRDTO = new RedisINCRDTO(RecoverConst.MONEY_USER_AMOUNT, parent.getUserId().toString(), profile.multiply(new BigDecimal(1000)).longValue());
                        list.add(redisINCRDTO);
                    }
                } catch (Exception e) {
                    throw new RuntimeException("添加用户推广资金变动出错2：" + e.getMessage());
                }
                addProfile(mapParent.get(userProperty.getParentId()), mapParent, gradeList, (parentLevel + 1), quota, list, comeUserId);
            }
        }
    }

    /**
     * 处理分润
     */
    private List<RedisINCRDTO> saveProfile(CardQuota quota, Long ownuserId){
        //获取所有的等级
        Map<Object, Object> gradeList = redishandler0.getHashMap(RecoverConst.USER_GRADE_REDIS_KEY, "");
        if (gradeList != null && gradeList.size() > 0) {
            //获取用户的所有上级
            UserProperty userProperty = userPropertyService.getOne(new QueryWrapper<UserProperty>().eq("user_id", ownuserId).eq("delete_flag", RecoverConst.DEL_FLAG_FALSE));
            if (userProperty != null && !userProperty.getGradeLevel().equals(UserGradeLevel.second_level.getCode())) {
                List<UserProperty> parents = getParents(userProperty);
                if (parents ==null || parents.size() == 0) {
                    return null;
                }
                Map<Long, UserProperty> mapParent =  parents.stream().collect(Collectors.toMap(UserProperty::getUserId, Function.identity()));
                List<RedisINCRDTO> list = new ArrayList<>();
                addProfile(userProperty, mapParent, gradeList, 1, quota, list, ownuserId);
                return list;
            }
        }
        return null;
    }

    private List<UserProperty> getParents(UserProperty userProperty) {
        List<UserProperty> upList = new ArrayList<>();
        if (StringUtils.isEmpty(userProperty.getRelationPath())) {
            return null;
        }
        String[] parentUserIds = userProperty.getRelationPath().split("-");
        List<String> userListT = Arrays.asList(parentUserIds);
        List<String> userList = new ArrayList<>(userListT);
        //userList.remove(userList.size()  - 1);
        if (userList.size() > 0) {
            upList = userPropertyService.list(new QueryWrapper<UserProperty>().in("user_id", userList).eq("delete_flag", RecoverConst.DEL_FLAG_FALSE));
            return upList;
        }
        return null;
    }

    /**
     * 添加用户资金记录
     * @param card
     */
    private void saveMoneyLog(Integer orderId, Card card, BigDecimal payAmount, String orderNo){
        Long oldAmount = 0L;
        Long newAmount = 0L;
        try {
            oldAmount = redishandler0.incr(RecoverConst.MONEY_USER_AMOUNT, card.getCreateUserId().toString(), 0);
            newAmount = redishandler0.incr(RecoverConst.MONEY_USER_AMOUNT, card.getCreateUserId().toString(), card.getAmount().multiply(new BigDecimal(1000)).longValue());
            MoneyLog moneyLog = new MoneyLog();
            moneyLog.setAmount(card.getAmount());
            moneyLog.setBusinessId(orderId);
            moneyLog.setBusinessNO(orderNo);
            moneyLog.setNewAmount(new BigDecimal("" + newAmount).divide(new BigDecimal(1000)));
            moneyLog.setOldAmount(new BigDecimal("" + oldAmount).divide(new BigDecimal(1000)));
            moneyLog.setType(MoneyLogType.CARD_ADD.getCode());
            moneyLog.setUserId(card.getCreateUserId());
            moneyLog.setUserName(card.getCreateUser());
            moneyLog.setRemark("您提交的" + card.getQuota() + "元" + card.getCardCataoryName() + "已经成功核销，实际面值：" + card.getAmount() + "元，到账金额"  + payAmount.toString());
            if (newAmount.equals(0L)) {
                throw new RuntimeException("添加用户资金变动出错1");
            }
            moneyLogService.save(moneyLog);
        } catch (Exception e) {
            if (!newAmount.equals(0L)) {
                redishandler0.incr(RecoverConst.MONEY_USER_AMOUNT, card.getCreateUserId().toString(), card.getAmount().multiply(new BigDecimal(1000)).negate().longValue());
            }
            throw new RuntimeException("添加用户资金变动出错2");
        }
    }

    private Serializable getKey(OrderParam param){
        return param.getOrderId();
    }

    private Page getPageContext() {
        return LayuiPageFactory.defaultPage();
    }

    private Order getOldEntity(OrderParam param) {
        return this.getById(getKey(param));
    }

    private Order getEntity(OrderParam param) {
        Order entity = new Order();
        ToolUtil.copyProperties(param, entity);
        return entity;
    }

}
